package zjy.android.guideapplication

import android.app.Activity
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlin.math.sqrt

class GuideItem(
        target: View? = null,
        private var targetId: Int? = null,
        private var hasStateBar: Boolean = true,
        private var shape: Shape? = null,
        private var padding: Padding? = null,
        private var hintResId: Int? = null,
        private var offsetX: Int = 0,
        private var offsetY: Int = 0,
        private var nextClickId: Int? = null,
        private var finishClickId: Int? = null,
        private var direction: Direction? = null
) : ICustomGuide {

    //highlight
    private var highlightRectF: RectF? = null
    private var highlightPath: Path? = null

    //hintView
    private var hintView: View? = null

    init {
//        target?.let {
//            targetId = it.id
//            initPoint(it)
//        }
        targetId = target?.id
    }

    fun setShape(shape: Shape): GuideItem {
        this.shape = shape
        return this
    }

    fun setPadding(padding: Padding): GuideItem {
        this.padding = padding
        return this
    }

    fun setHintResId(hintResId: Int): GuideItem {
        this.hintResId = hintResId
        return this
    }

    fun setOffsetX(offsetX: Int): GuideItem {
        this.offsetX = offsetX
        return this
    }

    fun setOffsetY(offsetY: Int): GuideItem {
        this.offsetY = offsetY
        return this
    }

    fun setNextClickId(nextClickId: Int): GuideItem {
        this.nextClickId = nextClickId
        return this
    }

    fun setFinishClickId(finishClickId: Int): GuideItem {
        this.finishClickId = finishClickId
        return this
    }

    fun setDirection(direction: Direction): GuideItem {
        this.direction = direction
        return this
    }

    fun setTargetId(targetId: Int?): GuideItem {
        this.targetId = targetId
        return this
    }

    fun setTarget(target: View): GuideItem {
        this.targetId = target.id
//        initPoint(target)
        return this
    }

    fun setTarget(target: View, hasStateBar: Boolean = true): GuideItem {
        this.targetId = target.id
//        initPoint(target)
        this.hasStateBar = hasStateBar
        return this
    }

    private fun emptyTarget(): Boolean = targetId == null

    private fun initHintView(context: Context) {
        hintResId?.let { id ->
            hintView = LayoutInflater.from(context).inflate(id, null).apply {
                if (emptyTarget()) {
                    layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
                } else {
                    layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
                    visibility = View.INVISIBLE
                    post {
                        highlightRectF?.let {
                            val centerX: Float = it.centerX()
                            val centerY: Float = it.centerY()
                            when (direction) {
                                Direction.TOP -> {
                                    y = it.top + offsetY - height
                                    x = offsetX + centerX - width / 2
                                }
                                Direction.LEFT -> {
                                    x = it.left + offsetX - width
                                    y = offsetY + centerY - height / 2
                                }
                                Direction.RIGHT -> {
                                    x = it.right + offsetX
                                    y = offsetY + centerY - height / 2
                                }
//                                Direction.BOTTOM -> {
//                                    y = it.bottom + offsetY
//                                    x = offsetX + centerX - width / 2
//                                }
                                else -> {
                                    y = it.bottom + offsetY
                                    x = offsetX + centerX - width / 2
                                }
                            }
                        }
                        visibility = View.VISIBLE
                    }
                }
            }
        }
    }

    private fun initPath() {
        highlightPath = Path().apply {
            when (shape) {
                Shape.RECTANGLE -> shapeRectangle(this)
                Shape.CIRCLE -> shapeCircle(this)
                Shape.OVAL -> shapeOval(this)
//                Shape.ROUND_RECTANGLE -> shapeRoundRectangle(this)
                else -> shapeRoundRectangle(this)
            }
        }
    }

    private fun shapeOval(highlightPath: Path) {
        highlightRectF?.let {
            highlightPath.addOval(it, Path.Direction.CW)
        }
    }

    private fun shapeRoundRectangle(highlightPath: Path) {
        highlightRectF?.let {
            highlightPath.addRoundRect(it, 25f, 25f, Path.Direction.CW)
        }
    }

    private fun shapeCircle(highlightPath: Path) {
        highlightRectF?.run {
            val w = width()
            val h = height()
            highlightPath.addCircle(centerX(), centerY(), (sqrt(w * w + h * h.toDouble()) / 2).toFloat(), Path.Direction.CW)
        }
    }

    private fun shapeRectangle(highlightPath: Path) {
        highlightRectF?.let {
            highlightPath.addRect(it, Path.Direction.CW)
        }
    }

    internal fun initHighlight(activity: Activity) {
        targetId?.let {
//            val target = activity.findViewById<View>(it)
            initPoint(activity.findViewById<View>(it))
        }
    }

    private fun initPoint(target: View) {
        var barHeight = 0
        if (hasStateBar) {
            barHeight = target.resources.run {
                getDimensionPixelSize(getIdentifier("status_bar_height", "dimen", "android"))
            }
        }
        target.post {
            val lt = IntArray(2)
            target.getLocationOnScreen(lt)
            highlightRectF = RectF().apply {
                (padding ?: Padding.all(0f)).let {
                    left = lt[0] - it.left
                    right = left + target.width + it.right
                    top = lt[1] - barHeight - it.top
                    bottom = top + target.height + it.bottom
                }
            }
        }
    }

    override fun onDrawHighlight(canvas: Canvas, path: Path, paint: Paint) {
        highlightRectF?.let {
            initPath()
            path.addPath(highlightPath!!)
        }
    }

    override fun onCreateGuideLayout(context: Context, next: Callback, finish: Callback): View? {
        initHintView(context)
        return hintView?.apply {
            nextClickId?.let { findViewById<View>(it).setOnClickListener { next.callback() } }
            finishClickId?.let { findViewById<View>(it).setOnClickListener { finish.callback() } }
        }
    }
}